package org.example;

import lombok.Data;
import org.example.node.AbstractNode;
import org.example.node.IndexNode;
import org.example.node.LeafNode;

import java.util.Map;

/**
 * @author lik
 * 不允许null值
 * 不允许key重复
 * 子节点最小值作为父节点索引值
 */
@Data
public class BalancePlusTree<K extends Comparable<K>, V> {

    /**
     * 根节点
     */
    private AbstractNode<K, V> root;

    /**
     * 最左叶子节点
     */
    private LeafNode<K, V> leftmostLeafNode;

    public BalancePlusTree() {
        root = new LeafNode<>();
        // 初始化时，最左叶子节点就是根节点
        leftmostLeafNode = (LeafNode<K, V>) root;
    }

    /**
     * 插入数据
     *
     * @param key   key
     * @param value value
     */
    public void insertOrUpdate(K key, V value) {
        if (key == null) {
            throw new NullPointerException("不好意思，主键不能为null");
        }
        root.insertOrUpdate(key, value, this);
    }

    /**
     * 查询
     *
     * @param key key
     * @return V
     */
    public V query(K key) {
        if (key == null) {
            return null;
        }
        return root.query(key);
    }

    /**
     * 删除
     *
     * @param key key
     */
    public void delete(K key) {
        if (key != null) {
            root.delete(key);
        }
    }

    public void print() {
        print(root, 1);
        System.out.println("=================");
    }

    private void print(AbstractNode<K, V> node, Integer high) {
        if (node instanceof IndexNode) {
            System.out.print("索引节点 树高：" + high + " ---> [");
            for (Map.Entry<K, AbstractNode<K, V>> child : ((IndexNode<K, V>) node).getChildren()) {
                System.out.print(child.getKey());
                System.out.print(",");
            }
            System.out.print("]");
            System.out.println();
            for (Map.Entry<K, AbstractNode<K, V>> child : ((IndexNode<K, V>) node).getChildren()) {
                print(child.getValue(), high + 1);
            }
        } else if (node instanceof LeafNode) {
            System.out.print("叶子节点 树高：" + high + " ---> [");
            for (Map.Entry<K, V> child : ((LeafNode<K, V>) node).getDataList()) {
                System.out.print(child.getKey());
                System.out.print(",");
            }
            System.out.print("]");
            System.out.println();
        }
    }

}
